package com.wwinsoft.framework.service.security;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.RequestKey;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class FilterSecurityMetadataSourceFactoryBean implements FactoryBean {
    @Autowired
    private ResourceDetailsService resourceDetailsService;

	public Object getObject() throws Exception {
		LinkedHashMap<RequestKey, Collection<ConfigAttribute>> requestMap = buildRequestMap();
		UrlMatcher matcher = getUrlMatcher();
		DefaultFilterInvocationSecurityMetadataSource definitionSource = new DefaultFilterInvocationSecurityMetadataSource(matcher, requestMap);
		return definitionSource;
	}

	@SuppressWarnings("unchecked")
	public Class getObjectType() {
		return FilterInvocationSecurityMetadataSource.class;
	}

	public boolean isSingleton() {
		return true;
	}

	protected UrlMatcher getUrlMatcher() {
		return new AntUrlPathMatcher();
	}

	protected LinkedHashMap<RequestKey, Collection<ConfigAttribute>> buildRequestMap() throws Exception {
		List<Map<String,Object>> srcMap = resourceDetailsService.getRequestMap();
		LinkedHashMap<RequestKey, Collection<ConfigAttribute>> distMap = new LinkedHashMap<RequestKey, Collection<ConfigAttribute>>();

		for (Map<String,Object> entry : srcMap) {
			RequestKey key = new RequestKey((String)entry.get(resourceDetailsService.URL),(String) entry.get(resourceDetailsService.METHOD));
            distMap.put(key, SecurityConfig.createList((String[]) entry.get(resourceDetailsService.AUTH_NAMES)));
		}

		return distMap;
	}
}
